{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 截取的数据处理部分\n",
    "下面是宏常量  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# 数据处理用\n",
    "import pandas\n",
    "import numpy\n",
    "import time\n",
    "import datetime\n",
    "import random\n",
    "import itertools\n",
    "\n",
    "\n",
    "\n",
    "trainType = [\"普客\", \"新空调快速\", \"新空调特快\", \"新空调直快\", \"动车\", \"高速\", \"城际\"]\n",
    "stationRegion = [\"济南\", \"济南西\", \"济南东\", \"大明湖\"]\n",
    "\n",
    "\n",
    "Excelpath = \"data.xlsx\"  # Excel时刻表输入文件路径，如爬取的时刻表或是是复制来的\n",
    "TextPath = \"train.txt\"  # 游戏时刻表文件输出路径\n",
    "# 速度和编组以及类型映射关系,0为普速1为动车2为高速，后续修改\n",
    "species = {'新空调普快': ['120', 'LPPPPPP', 0], '新空调快速': ['120', 'LPPPPPP', 0],\n",
    "           '新空调特快': ['140', 'LPPPPPP', 0], '新空调直快': ['160', 'LPPPPPP', 0],\n",
    "           '动车': ['200', 'LPPL', 1], '城际': ['200', 'LPPL', 1], '高速': ['300', 'LPPLLPPL', 2]}\n",
    "species1 = {'K': ['120', 'LPPPPPP', 0], 'T': ['140', 'LPPPPPP', 0], 'Z': ['160', 'LPPPPPP', 0],\n",
    "            'D': ['200', 'LPPL', 1], 'C': ['200', 'LPPL', 1], 'G': ['300', 'LPPLLPPL', 2]}\n",
    "\n",
    "# 车站-编号,掉向,用时以及运行车辆种类映射关系\n",
    "# 图片左(0)右(1)侧线路key值相同则掉向,\n",
    "# 国铁车辆行走左侧,2为数据为左侧股道编号\n",
    "# [车站编号,车站所在侧(0为左侧),车辆进场股道,车辆离场行走股道,到达中心车站所用时间]\n",
    "station = {'武汉站': ['a', -1, 0, 0, 0 ], '武汉动车所': ['c', 1, 0, 0, 5],\n",
    "           '京广高速咸宁北方向': ['b', 1, 2, 1, 5 ], '武九客专葛店南方向': ['d', 1, 2, 1, 4],\n",
    "           '京广高速孝感北方向': ['e', 1, 1, 2, 10 ], '沪蓉线红安西方向': ['f', 0, 1, 2, 10],\n",
    "           '沪蓉线汉口方向': ['h', 0, 1, 2, 5], '丹水池联络线汉口方向': ['i', 0, 1, 2, 7], }\n",
    "\n",
    "# 线路和车站关系，主要用于从车站-值获取线路-键\n",
    "route1 = { '武汉动车所': [\"武汉\"],\n",
    "           '京广高速咸宁北方向': [ ], '武九客专葛店南方向': [\"葛店南\",\"鄂州\",\"\"],\n",
    "           '京广高速孝感北方向': [ ], '沪蓉线红安西方向': [],\n",
    "           '沪蓉线汉口方向': [\"汉口\"], '丹水池联络线汉口方向': [], }\n",
    "# 两个合在一起写太难看\n",
    "\n",
    "\n",
    "# 车型关系--待完善，后续待交路表部分完成后会使用对应映射而不是上面的简单类型映射\n",
    "marshalling = {'CHR380BL': [], 'CHR380B': [], 'CHR380B重连': []}\n",
    "\n",
    "\n",
    "ThisStation = '济南西站'\n",
    "TotalPlat = 18\n",
    "# track = {}\n",
    "\n",
    "\n",
    "# 模拟器信息\n",
    "desired_caps = {\n",
    "    'platformName': 'Android',  # 被测手机是安卓\n",
    "    'platformVersion': '9',  # 手机安卓版本\n",
    "    'deviceName': 'emulator-5554:5555',  # 设备名和映射连接端口，安卓手机可以随意填写\n",
    "\n",
    "    'appPackage': 'com.lltskb.lltskb',  # 启动APP Package名称\n",
    "    'appActivity': '.ui.splash.SplashActivity',  # 启动Activity名称\n",
    "\n",
    "    'unicodeKeyboard': True,  # 使用自带输入法，输入中文时填True\n",
    "    'resetKeyboard': True,  # 执行完程序恢复原来输入法\n",
    "    'noReset': True,       # 不要重置App\n",
    "    'newCommandTimeout': 6000,\n",
    "    'automationName': 'UiAutomator2'\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 第三部分，处理获取到的数据并生成游戏样式的时刻表\n",
    "这部分最为重要，按照游戏中时刻表格式分为若干部分  \n",
    "车辆信息部分，如车次编号，速度等级等信息  \n",
    "停站信息部分，有四部分按顺序分别为 停站编号，停站股道，停站时刻，停站时间。这四部分会单独拆开分别生成  \n",
    "例： G7 COMMUTER 300 LPPLLPPL X1 : f#1#11:17:00#0 d#6#11:23:00#3 a#1#11:33:00#0  \n",
    "\n",
    "内容|完成度|实现原理|近期改良计划|远期优化计划\n",
    "---|---|---|---|---\n",
    "车辆信息|较为完善|目前为仅按照车次编号和类型生成|近期暂无|完善交路表爬取以修改速度级和编组信息立折车次信息完善\n",
    "停站信息-停站编号|完善|依照游戏自身设置直接映射|暂无|暂无\n",
    "停站信息-停站股道|较为完善|selenium按照web自动化12306查询获取 <br>appnium部分按照车次信息查询--检票口获得|完善车次查询部分以获得<br>停站检票口信息|使用车站大屏来获得无法离线查询的车站信息\n",
    "停站信息-停站时刻|完善|按照到站时间和出发时间推算|近期暂无|加上线路所映射行车进路部分\n",
    "停站信息-停站时间|完善|按照到站时间和出发时间计算|近期暂无|立折车次停站时间等按照交路表推算\n",
    "整体上|较为完善|使用apply(lambda) 来进列映射整处理而不是按照行单个处理|暂无  \n",
    "\n",
    "### 第三部分第〇小部分--处理用函数定义\n",
    "#### 内容  \n",
    "目前按照上面输入为上面自动化爬取获取到csv样式的txt文件，输出为按照车站为单位的数据  \n",
    "1. 首先去除空行和重复值等基本操作进行数据提纯   \n",
    "2. 在统一处理如得到部分信息如停站时间和始发终到的处理，  \n",
    "3. 可以获得中心车站的停站时间信息等  \n",
    "4. 同时预先定义需要使用的处理函数  \n",
    "\n",
    "#### 实现原理  \n",
    "1. 整体上以处理dataframe为主，文件→dataframe→文本\n",
    "2. 大量使用.apply相应处理函数来处理列，尽可能少使用匿名函数来增加可读性\n",
    "3. 由文件读出的大表来初步处理groupby 再对想到较小的表来处理\n",
    "4.\n",
    "\n",
    "\n",
    "#### 待完善/优化的部分\n",
    "近期暂无计划，远期计划加入进路映射以使用线路所来优化自动化  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "def dealTime(datafr: pandas.DataFrame) -> pandas.DataFrame:\n",
    "    # 对于始发车和终到车进行时间处理，默认相同\n",
    "    for idx, row in datafr.iterrows():\n",
    "        if row[\"到时\"] == \"--:--\":\n",
    "            row[\"到时\"] = row[\"开时\"]\n",
    "        elif row[\"开时\"] == \"--:--\":\n",
    "            row[\"开时\"] = row[\"到时\"]\n",
    "    # 计算停站时间\n",
    "    datafr[\"到时\"] = pandas.to_datetime(datafr[\"到时\"])\n",
    "    datafr[\"开时\"] = pandas.to_datetime(datafr[\"开时\"])\n",
    "    # 实发终到设置停站时间\n",
    "    # pd[\"停站时间\"].replace(0,10,inplace=True)\n",
    "\n",
    "    return datafr\n",
    "\n",
    "\n",
    "def stopStTime(stopTime: pandas.Timedelta) -> int:\n",
    "    a = int(stopTime.seconds/60)  # 处理为数值类型的分钟时间\n",
    "    # 始发或是终到的时间是随机的\n",
    "    return a if a > 0 else random.randint(10, 30)\n",
    "\n",
    "\n",
    "def ModtimeStr(switchTime: pandas.Timestamp) -> str:\n",
    "    # 处理为仅有时分秒样式的字符串格式的时间\n",
    "    return switchTime.strftime(\"%H:%M:%S\")\n",
    "\n",
    "\n",
    "def speMarType(traincode: str) -> str:  # 目前获取编组信息的方式\n",
    "    til = species1[traincode[0]]  # 处理获取车辆信息字符串部分\n",
    "    return \"{cod} COMMUTER {speed} {mar} X1\".format(cod=traincode, speed=til[0], mar=til[1])\n",
    "\n",
    "\n",
    "def checkin(entrance: str) -> int:\n",
    "    # 终到车\n",
    "    res = 0\n",
    "    if entrance == \"无检票口信息\":\n",
    "        res = 0\n",
    "    else:  # 格式类似检票口15A，替换掉其他字样\n",
    "        res = int(entrance.strip(\"检票口AB\"))\n",
    "    return res\n",
    "\n",
    "\n",
    "def prevnextST(stopSt: list[str], stIdx: int) -> list[str]:\n",
    "    # 返回结果，获取目标车站的前后车站\n",
    "    res = [\"\", \"\"]\n",
    "    res1 = [\"\", \"\"]\n",
    "    if stIdx == 0:  # 始发车视为始发车站和下一站\n",
    "        res = [stopSt[0], stopSt[1]]\n",
    "    elif stIdx == len(stopSt)-1:  # 终到车视为前一站和终到站\n",
    "        res = [stopSt[len(stopSt)-2], stopSt[len(stopSt)-1]]\n",
    "    else:  # 中间站\n",
    "        res = [stopSt[stIdx-1], stopSt[stIdx+1]]\n",
    "    # 判断并修改进路\n",
    "    for k, v in route1.items():\n",
    "        # 把车站名映射为线路\n",
    "        if res[0] in v:\n",
    "            res1[0] = k\n",
    "        elif res[1] in v:\n",
    "            res1[1] = k\n",
    "    return res1\n",
    "\n",
    "\n",
    "def arrLeaTime(t1: pandas.Timestamp, st: list[str], mark: int) -> str:\n",
    "    # 选取是上一站还是下一站\n",
    "    tarst = st[mark]\n",
    "    useTime = station[tarst][4]\n",
    "    if mark == 0:  # 进场减时间\n",
    "        res = t1-datetime.timedelta(minutes=useTime)\n",
    "    else:  # 离场加时间\n",
    "        res = t1+datetime.timedelta(minutes=useTime)\n",
    "    # 返回时分秒格式的字符串\n",
    "    return res.strftime(\"%H:%M:%S\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 第三部分第一小部分--爬取信息整体初步处理 \n",
    "#### 内容\n",
    "\n",
    "\n",
    "#### 实现原理\n",
    "\n",
    "\n",
    "#### 待完善/优化的部分"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 手动建立映射关系,别的方法不会\n",
    "\n",
    "\n",
    "def processTrains(fn: str, targetSt: str) -> pandas.DataFrame:\n",
    "    # 处理产生初步所需信息的数据框\n",
    "    trainsFrame = pandas.read_csv(filepath_or_buffer=fn,\n",
    "                                  sep=\",\", encoding=\"utf8\", header=None)\n",
    "    trainsFrame.columns = [\"车次\",  \"停站\", \"到时\", \"开时\", \"检票口\", \"drop1\"]\n",
    "    trainsFrame.drop(columns=[\"drop1\"], inplace=True)\n",
    "\n",
    "    trainsFrame = dealTime(trainsFrame)  # 初步处理时间\n",
    "    trainsFrame.sort_values(by=[\"车次\", \"到时\"], inplace=True)  # 归类排序\n",
    "    # 整理为分钟样式的停站时间\n",
    "    #trainsFrame[\"停站时间\"] = trainsFrame[\"停站时间\"].apply(lambda x: stopStTime(x))\n",
    "    trainsFrame.reset_index(drop=True, inplace=True)\n",
    "    # 按照车次分组为列表，同时车次不作为索引以便于操作\n",
    "    tfgp = trainsFrame.groupby(by=[\"车次\"], as_index=False).agg(list)\n",
    "    # 获取目标停站的索引值，设置为一个辅助列\n",
    "    tfgp[\"auxIdx\"] = tfgp['停站'].apply(lambda x: x.index(targetSt))\n",
    "\n",
    "    # 获取前后停站以得到更好的交路映射\n",
    "    tfgp[\"目标前后站\"] = tfgp.apply(\n",
    "        lambda x: prevnextST(x[\"停站\"], x[\"auxIdx\"]), axis=1)\n",
    "    # 获取其他信息\n",
    "    tfgp[\"目标站到时\"] = tfgp.apply(lambda x: x[\"到时\"][x[\"auxIdx\"]], axis=1)\n",
    "    tfgp[\"目标站开时\"] = tfgp.apply(lambda x: x[\"开时\"][x[\"auxIdx\"]], axis=1)\n",
    "    tfgp[\"目标站检票口\"] = tfgp.apply(lambda x: x[\"检票口\"][x[\"auxIdx\"]], axis=1)\n",
    "\n",
    "    # 提取需要的信息为新的dataframe\n",
    "    trainInfoNeed = tfgp[[\"车次\", \"目标站到时\", \"目标站开时\", \"目标站检票口\", \"目标前后站\"]]\n",
    "    trainInfoNeed.columns = [\"车次\", \"到时\", \"开时\", \"检票口\", \"前后站\"]\n",
    "    # print(trainInfoNeed.head())\n",
    "\n",
    "    return trainInfoNeed\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  第三部分第二小部分 -- 处理生成最终dataframe样式的数据 \n",
    "\n",
    "#### 内容\n",
    "按照上面的函数处理数据，最终处理生成有进(离)场时间/股道 等信息的dataframe,之后生成字符串导出    \n",
    "这里分为两部分，车辆信息的trainframe和路径时刻表的stationframe,  \n",
    " 'D8176 COMMUTER 200 LPPL X1 : b#2#18:08:00#0 d#0#18:16:00#14 e#0#18:36:00#0 ',\n",
    "\n",
    "#### 实现原理\n",
    "> 1. generateTrainInfo 即为文字版时刻表分号前的内容，生成车次信息部分  \n",
    ">> 1.1. 考虑到内容只需做车次编号，速度等级和编组信息则按照车次首位ktz生成    \n",
    ">> 2.1. 编组信息尚未准备开始   \n",
    "> 2. generateArriveLeave 即为文字版时刻表分号后的内容，生成进场和离场信息部分  \n",
    ">> 2.1. 基于停站的上一站完善进路的刻画\n",
    ">> 2.2. 本身进场和离场处理基本类似，这里使用一个mark来进行区分\n",
    "> 3. generateMainSt 即为区域核心车站生成部分  \n",
    ">> 3.1. 绝大多数信息已经在前面处理完成，这里主要是处理格式问题  \n",
    ">> 3.2. 车站名称的填充放在最后，防止由于数据全空导致填充失败  \n",
    "\n",
    "#### 改进计划  \n",
    "1. 对于分场式车站采用进场线路--对应线路所来映射，加入线路所映射部分\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "\n",
    "def generateRoute(dataser: pandas.Series):\n",
    "    # 进行中，对于分场式车站采用线路所映射进路\n",
    "    s1 = \"黄河南线路所\"\n",
    "    s2 = \"大漠刘线路所\"\n",
    "    return None\n",
    "#\n",
    "\n",
    "\n",
    "def generateArriveLeave(datafr: pandas.DataFrame, mark) -> pandas.DataFrame:\n",
    "    # 生成进场/离场信息\n",
    "    # mark=0为进场，mark=1为离场\n",
    "    ALStDF = pandas.DataFrame(columns=['车站名称', '股道', '到达时间', '停站时间'])  # 进场信息\n",
    "    # 按照信息来映射进场/离场线路\n",
    "    ALStDF['车站名称'] = datafr[\"前后站\"].apply(lambda x: x[mark])\n",
    "    # 按照信息来映射进场/离场股道\n",
    "    ALStDF['股道'] = ALStDF['车站名称'].apply(lambda x: station[x][2+mark])\n",
    "    # 时间作差\n",
    "    ALStDF['到达时间'] = datafr.apply(\n",
    "        lambda x: arrLeaTime(x[\"到时\"], x[\"前后站\"], mark), axis=1)\n",
    "    # 进程默认经过不停车\n",
    "    ALStDF['停站时间'] = 0\n",
    "\n",
    "    return ALStDF\n",
    "\n",
    "\n",
    "def generateMainSt(datafr: pandas.DataFrame):\n",
    "    # 生成中心停站信息\n",
    "    MainStDF = pandas.DataFrame(columns=['车站名称', '股道', '到达时间', '停站时间'])  # 进场信息\n",
    "\n",
    "    # 计算停站时长，得到整形类型的时长，非浮点数没有.0便于写入文件\n",
    "    MainStDF[\"停站时间\"] = (datafr[\"开时\"]-datafr[\"到时\"]\n",
    "                        ).apply(lambda x: stopStTime(x))\n",
    "    # 计算并规整进场离场和停站时间，将三个到时改为游戏时分秒格式 hh:mm:ss\n",
    "    MainStDF[\"到达时间\"] = datafr[\"到时\"].apply(lambda x: ModtimeStr(x))\n",
    "    # 按照相应格式处理车站检票口为对应形式\n",
    "    MainStDF[\"股道\"] = datafr[\"检票口\"].apply(lambda x: checkin(x))\n",
    "    # 填充车站为中心车站\n",
    "    MainStDF[\"车站名称\"].fillna(value=\"济南西\", inplace=True)\n",
    "    return MainStDF\n",
    "\n",
    "\n",
    "def generateTrainInfo(dataser: pandas.Series) -> pandas.Series:\n",
    "    # 生成车次信息\n",
    "    res = dataser.apply(lambda x: speMarType(x))\n",
    "    print(res.head())\n",
    "    return res\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 第四部分 -- 生成对应样式的字符串并写入文件\n",
    "\n",
    "### 内容  \n",
    "1. 整合之前的数据来生成符合样式的dataframe数据合集  \n",
    "2. 生成csv长字符串并按行分割为一个个的端数据  \n",
    "3. 最终连接处理生成结果，不替换代号便于后续检查    \n",
    "\n",
    "### 实现原理\n",
    "整合数据和字符串处理\n",
    "\n",
    "### 改进计划  \n",
    "暂无"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "def generateStr(fn: str)->list:\n",
    "    #生成游戏样式的字符串\n",
    "    f = open(file=fn, encoding=\"utf8\", mode=\"w\")\n",
    "    res=[]\n",
    "    for i in range(0, len(arriveStDF)):\n",
    "        #format为对应顺序格式\n",
    "        tf = \"{train} : {arrive} {stop} {leave}\".format(\n",
    "            train=trainstr[i], arrive=arrivestr[i], stop=stopstr[i], leave=leavestr[i])\n",
    "        print(tf)\n",
    "        res.append(tf) #将结果写入文件\n",
    "        f.write(tf+\"\\n\")\n",
    "\n",
    "    f.close()\n",
    "    return res\n",
    "\n",
    "\n",
    "at = processTrains(\"ltInfo.txt\", \"济南西\")\n",
    "#生成dataframe格式的数据\n",
    "arriveStDF = generateArriveLeave(at, mark=0)\n",
    "leaveStDF = generateArriveLeave(at, mark=1)\n",
    "stopStDF = generateMainSt(at)\n",
    "trainDF = generateTrainInfo(at[\"车次\"])\n",
    "\n",
    "#按照四部分生成需求的字符格式，使用to_csv函数来生成\n",
    "arrivestr = arriveStDF.to_csv(\n",
    "    sep=\"#\", header=False, index=False).split(sep=\"\\r\\n\")\n",
    "leavestr = leaveStDF.to_csv(sep=\"#\", header=False, index=False).split(sep=\"\\r\\n\")\n",
    "stopstr = stopStDF.to_csv(sep=\"#\", header=False, index=False).split(sep=\"\\r\\n\")\n",
    "trainstr = trainDF.to_csv(header=False, index=False).split(sep=\"\\r\\n\")\n",
    "\n",
    "generateStr(\"测试.txt\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "-------  \n",
    "\n",
    "## 第五部分，可视化用于分析分布如高峰期和主要类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# 对于该车站群组（地区）时间段内的所有车次信息\n",
    "\n",
    "\n",
    "def getStationProid(datafr: pandas.DataFrame, at: int) -> dict:\n",
    "    # 预先分类，按照小时\n",
    "    datagruop = datafr.groupby([\"到时-小时\", \"停站\", \"列车类型\"])\n",
    "    # print(datagruop.groups)\n",
    "    regionInfo = {}\n",
    "\n",
    "    # 对于每个车站的每种类型的列车\n",
    "    for sr in stationRegion:\n",
    "        # 好像只能分开写两层了\n",
    "        regionInfo[sr+\"trainCode\"] = []\n",
    "        regionInfo[sr+\"trainCount\"] = []\n",
    "        for tt in trainType:\n",
    "            try:  # 查找符合条件的群组\n",
    "                i = datagruop.get_group((at, sr, tt))\n",
    "\n",
    "            except KeyError:  # 索引找不到就是0\n",
    "                regionInfo[sr+\"trainCount\"].append(0)\n",
    "                # regionInfo[\"trainCode\"].append(None)\n",
    "            else:  # 如果没问题，添加回去长度\n",
    "\n",
    "                regionInfo[sr+\"trainCode\"].append(i[\"车次\"].tolist())\n",
    "                regionInfo[sr+\"trainCount\"].append(len(i))\n",
    "        regionInfo[sr+\"trainCode\"] = sum(regionInfo[sr+\"trainCode\"], [])\n",
    "    # 解包嵌套的列表\n",
    "    # print(regionInfo)\n",
    "\n",
    "    return regionInfo\n",
    "\n",
    "\n",
    "def getTrainProid(datafr: pandas.DataFrame, at: int) -> dict:\n",
    "    # 预先分类，数据分析用\n",
    "    datagruop = datafr.groupby([\"到时-小时\", \"停站\", \"列车类型\"])\n",
    "    # print(datagruop.groups)\n",
    "    regionInfo = {}\n",
    "\n",
    "    # 对于每个车站的每种类型的列车\n",
    "    for tt in trainType:\n",
    "        # 好像只能分开写两层了\n",
    "        regionInfo[tt+\"trainCode\"] = []\n",
    "        regionInfo[tt+\"stationName\"] = []\n",
    "        regionInfo[tt+\"stationCount\"] = []\n",
    "        for st in stationRegion:\n",
    "            try:  # 查找符合条件的群组\n",
    "                i = datagruop.get_group((at, st, tt))\n",
    "\n",
    "            except KeyError:  # 索引找不到就是0\n",
    "                regionInfo[tt+\"stationCount\"].append(0)\n",
    "                # regionInfo[\"trainCode\"].append(None)\n",
    "            else:  # 如果没问题，添加回去长度\n",
    "                regionInfo[tt+\"trainCode\"].append(i[\"车次\"].tolist())\n",
    "                regionInfo[tt+\"stationName\"].append(i[\"停站\"].tolist())\n",
    "                regionInfo[tt+\"stationCount\"].append(len(i))\n",
    "\n",
    "        regionInfo[tt+\"stationName\"] = sum(regionInfo[tt+\"stationName\"], [])\n",
    "    # 解包嵌套的列表\n",
    "    # print(regionInfo)\n",
    "\n",
    "    return regionInfo\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.11.2"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
